/* SPF (Sender Policy Framework) implementation.

Translation to C Copyright (c) 2007 Roberto Alsina <ralsina@kde.org>
Copyright (c) 2003, Terence Way
Portions Copyright (c) 2004,2005,2006 Stuart Gathman <stuart@bmsi.com>
Portions Copyright (c) 2005,2006 Scott Kitterman <scott@kitterman.com>
This module is free software, and you may redistribute it and/or modify
it under the same terms as Python itself, so long as this copyright message
and disclaimer are retained in their original form.

IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

For more information about SPF, a tool against email forgery, see
http://www.openspf.org/

For new versions check out http://code.google.com/p/raspf

*/

#ifndef RA_SPF_H
#define RA_SPF_H

#define RE_CHAR "%(%|_|-|(\\{[^\\}]*\\}))"
#define RE_ARGS "([0-9]*)(r?)([^0-9a-zA-Z]*)"
#define RE_CIDR "/(0|[1-9]*)$"
#define RE_DUAL_CIDR "//(0|[1-9]*)$"
#define RE_MODIFIER "^([a-z][-a-z0-9_\\.]*)="
#define RE_IP4 "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|0)\\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|0)\\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|0)\\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|0)$"
#define RE_TOPLAB "^([%\\{\\}a-zA-Z0-9]([%\\ /{\\}a-zA-Z0-9\\-]*[a-zA-Z0-9])?\\.)*[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?$"
#define RE_SPF "^v=spf1$|^v=spf1 "
#define TRUSTED_FORWARDERS "v=spf1 ?include:spf.trusted-forwarder.org -all"

#define MAX_RECURSION 20
//RFC 4408 Para 10.1
#define MAX_LOOKUP  10
//RFC 4408 Para 10.1
#define MAX_PTR 10
//RFC 4408 Para 10.1
#define MAX_MX 10

#define DEFAULT_SPF "v=spf1 a/24 mx/24 ptr"

#include "excc/exception-local.h"

typedef struct mechanism {
    bstring mech;
    bstring m;
    bstring arg;
    int cidrlength;
    bstring result;
    exception_t error;
} mechanism;

void destroy_mechanism(mechanism m);

struct dns_ctx;

typedef struct spf_query {
    bstring i;
    bstring s;
    bstring l;
    bstring d;
    bstring h;
    bstring v;
    bstring p;
    bstring o;
    bstring r;
    bstring c;
    bstring A;
    //bstring ip;
    int cidrmax;

    bstring ident;
    int lookups;
    bstring libspf_local;
    int strict;
    bstring error;

    struct hashtable *exps;
    struct hashtable *defexps;
    struct hashtable *options;

    exception_t perm_error;
    bstring prob;

    mechanism mech[1000];
    int mcount;
    struct dns_ctx *ctx;

} spf_query ;




struct hashtable *RESULTS;
struct hashtable *EXPLANATIONS;
struct hashtable *COMMON_MISTAKES;
struct hashtable *JOINERS;


typedef struct spf_response {
    char *response;
    int code;
    char *explanation;
} spf_response;


spf_response spf_check (const char *ip, const char *sender,
                        const char *helo, const char *local,
                       const char *receiver);

struct spf_query *spf_query_init (const char *i, const char *s, const char *h,
                                  const char *local,
                                  const char *receiver,
                                  int strict);

void spf_query_destroy (spf_query *q);

struct bstrList *re_split(const char *string, const char *pattern);
bstring re_split2(const char *string, const char *pattern,unsigned char joiner);
struct bstrList *re_findall(const char *string, const char *pattern);
bstring re_find(const char *string, const char *pattern, int *begin, int *end);
struct bstrList *split(bstring str,bstring delimiters,bstring joiner);
bstring url_encode( const char* str );

bstring spf_query_expand (spf_query *q,bstring str,int stripdot);
void spf_query_set_explanation(spf_query *q,const char *exp);
bstring spf_query_get_explanation(spf_query *q, bstring spec);
bstring expand_one(bstring expansion,bstring str,bstring joiner);
bstring spf_query_getp(struct spf_query *q);
void spf_query_set_ip(spf_query *q, const char *i);
exception_t spf_query_note_error(spf_query *q, bstring msg);
void spf_query_check_lookups(spf_query *q);
int spf_query_cidrmatch (spf_query *q,struct bstrList *list,int n);
int spf_query_cidrmatch1 (spf_query *q,bstring _ip,int n);


bstring spf_query_check(struct spf_query *q, bstring spf,
                    int *mta_status_code,
                    bstring *explanation);

bstring spf_query_check1 (struct spf_query *q,
                      bstring spf,bstring d,
                      int recursion,
                      int *mta_status_code,
                      bstring *explanation);

bstring spf_query_check0 (struct spf_query *q,
                      bstring spf,int recursion,
                      int *mta_status_code,
                      bstring *explanation);

bstring spf_query_best_guess (spf_query *q, bstring spf,
                              int *mta_status_code,
                              bstring *explanation);

mechanism spf_query_validate_mechanism(struct spf_query *q,bstring mech);
struct bstrList *spf_query_validated_ptrs( spf_query *q);
void parse_mechanism (bstring mech,bstring d, bstring *name, bstring *domain,
                 int *cidr, int *cidr6);

bstring spf_query_get_header(spf_query *q,bstring res,bstring receiver);

bstring insert_libspf_local_policy (bstring spftxt,bstring local);

void spf_init (void);
void spf_close (void);

int match(const char *string, char *pattern);

void
    split_email (const char *s,const char *h ,
                 bstring *l, bstring *d);

int in_list (bstring str,struct bstrList *list);
int domainmatch (struct bstrList *l,bstring domainsuffix);
bstring spf_query_expand_domain( spf_query *q, bstring arg );


int beqcstr(bstring b,const char *s);


bstring spf_query_dns_spf(spf_query *q,bstring d);
struct bstrList *spf_query_dns_txt(spf_query *q,bstring domainname);
struct bstrList *spf_query_dns_a(spf_query *q,bstring domainname, bstring A);
struct bstrList *spf_query_dns_mx(spf_query *q,bstring domainname);
struct bstrList *spf_query_dns_ptr(spf_query *q,bstring ip);
struct bstrList *spf_query_dns_99(spf_query *q,bstring domainname);
const char *dns_error_text(spf_query *q);

struct tagbstring _SPF=bsStatic("SPF");
struct tagbstring _TXT=bsStatic("TXT");
struct tagbstring _MX=bsStatic("MX");
struct tagbstring _A=bsStatic("A");
struct tagbstring _AAAA=bsStatic("AAAA");
struct tagbstring _PTR=bsStatic("PTR");
struct tagbstring _TO=bsStatic("TIMEOUT");
struct tagbstring _NONE=bsStatic("NONE");


int validate_domain_spec ( const char *s);
int validate_ipv4 ( const char *s);

#endif

